package com.gufe.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.github.pagehelper.Page;
import com.gufe.common.core.domain.entity.SysDept;
import com.gufe.common.core.domain.model.LoginUser;
import com.gufe.common.core.page.PageDomain;
import com.gufe.common.core.page.TableSupport;
import com.gufe.system.common.BaseSystemService;
import com.gufe.system.domain.BaseSystemOrg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.gufe.common.annotation.DataScope;
import com.gufe.common.constant.UserConstants;
import com.gufe.common.core.domain.entity.SysRole;
import com.gufe.common.core.domain.entity.SysUser;
import com.gufe.common.exception.ServiceException;
import com.gufe.common.utils.SecurityUtils;
import com.gufe.common.utils.StringUtils;
import com.gufe.common.utils.spring.SpringUtils;
import com.gufe.system.domain.SysRoleDept;
import com.gufe.system.domain.SysRoleMenu;
import com.gufe.system.domain.SysUserRole;
import com.gufe.system.mapper.SysRoleDeptMapper;
import com.gufe.system.mapper.SysRoleMapper;
import com.gufe.system.mapper.SysRoleMenuMapper;
import com.gufe.system.mapper.SysUserRoleMapper;
import com.gufe.system.service.ISysRoleService;

/**
 * 角色 业务层处理
 * 
 * @author ruoyi
 */
@Service
public class SysRoleServiceImpl implements ISysRoleService
{
    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysRoleDeptMapper roleDeptMapper;

    @Autowired
    private BaseSystemService baseSystemService;

    /**
     * 根据条件分页查询角色数据
     * 
     * @param role 角色信息
     * @return 角色数据集合信息
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<SysRole> selectRoleList(SysRole role)
    {
        // 1. 从外部接口获取所有基础数据
        BaseSystemOrg baseSystemOrg = baseSystemService.getSystemOrg().getData();
        List<SysRole> sysRoleList = baseSystemOrg.getSysRoleList();
        List<SysUser> sysUserList = baseSystemOrg.getSysUserList();
        List<SysUserRole> sysUserRoleList = baseSystemOrg.getSysUserRoleList();
        List<SysDept> sysDeptList = baseSystemOrg.getSysDeptList();

        // 2. 构建必要的映射关系（提升性能）
        Map<Long, SysUser> userMap = sysUserList.stream()
                .collect(Collectors.toMap(SysUser::getUserId, u -> u));

        Map<Long, SysDept> deptMap = sysDeptList.stream()
                .collect(Collectors.toMap(SysDept::getDeptId, d -> d));

        // 角色 -> 用户列表 映射
        Map<Long, List<Long>> roleIdToUserIds = sysUserRoleList.stream()
                .collect(Collectors.groupingBy(
                        SysUserRole::getRoleId,
                        Collectors.mapping(SysUserRole::getUserId, Collectors.toList())
                ));

        // 部门 -> 用户列表 映射
        Map<Long, List<Long>> deptIdToUserIds = sysUserList.stream()
                .filter(u -> u.getDeptId() != null)
                .collect(Collectors.groupingBy(
                        SysUser::getDeptId,
                        Collectors.mapping(SysUser::getUserId, Collectors.toList())
                ));

        // 3. 获取当前登录用户（用于数据权限判断）
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null || loginUser.getUser() == null) {
            return Collections.emptyList(); // 安全兜底
        }
        SysUser currentUser = loginUser.getUser();
        Long currentUserId = currentUser.getUserId();
        Long currentDeptId = currentUser.getDeptId();

        // 4. 获取当前用户角色的数据权限范围（dataScope）
        String dataScope = "1"; // 默认：所有数据权限
        if (currentUser.getRoles() != null && !currentUser.getRoles().isEmpty()) {
            dataScope = currentUser.getRoles().get(0).getDataScope();
        }

        // 5. 根据 dataScope 计算“当前用户有权查看”的角色 ID 集合
        Set<Long> allowedRoleIds = new HashSet<>();

        switch (dataScope) {
            case "1": // 所有数据权限
                allowedRoleIds.addAll(sysRoleList.stream()
                        .filter(r -> "0".equals(r.getDelFlag()))
                        .map(SysRole::getRoleId)
                        .collect(Collectors.toSet()));
                break;

            case "2": // 自定义数据权限
                Set<Long> customDeptIds = new HashSet<>();
                for (SysRole r : sysRoleList) {
                    if (r.getDeptIds() != null) {
                        customDeptIds.addAll(Arrays.asList(r.getDeptIds()));
                    }
                }
                Set<Long> usersInCustomDepts = customDeptIds.stream()
                        .flatMap(deptId -> deptIdToUserIds.getOrDefault(deptId, Collections.emptyList()).stream())
                        .collect(Collectors.toSet());
                allowedRoleIds = sysUserRoleList.stream()
                        .filter(ur -> usersInCustomDepts.contains(ur.getUserId()))
                        .map(SysUserRole::getRoleId)
                        .filter(roleId -> {
                            SysRole r = sysRoleList.stream()
                                    .filter(sr -> sr.getRoleId().equals(roleId))
                                    .findFirst()
                                    .orElse(null);
                            return r != null && "0".equals(r.getDelFlag());
                        })
                        .collect(Collectors.toSet());
                break;

            case "3": // 本部门数据权限
                if (currentDeptId != null) {
                    List<Long> usersInCurrentDept = deptIdToUserIds.getOrDefault(currentDeptId, Collections.emptyList());
                    allowedRoleIds = sysUserRoleList.stream()
                            .filter(ur -> usersInCurrentDept.contains(ur.getUserId()))
                            .map(SysUserRole::getRoleId)
                            .filter(roleId -> {
                                SysRole r = sysRoleList.stream()
                                        .filter(sr -> sr.getRoleId().equals(roleId))
                                        .findFirst()
                                        .orElse(null);
                                return r != null && "0".equals(r.getDelFlag());
                            })
                            .collect(Collectors.toSet());
                }
                break;

            case "4": // 本部门及以下数据权限
                if (currentDeptId != null) {
                    SysDept currentDept = deptMap.get(currentDeptId);
                    if (currentDept != null) {
                        Set<Long> subDeptIds = getSubDeptIds(currentDept, deptMap, sysDeptList);
                        Set<Long> usersInSubDepts = subDeptIds.stream()
                                .flatMap(deptId -> deptIdToUserIds.getOrDefault(deptId, Collections.emptyList()).stream())
                                .collect(Collectors.toSet());
                        allowedRoleIds = sysUserRoleList.stream()
                                .filter(ur -> usersInSubDepts.contains(ur.getUserId()))
                                .map(SysUserRole::getRoleId)
                                .filter(roleId -> {
                                    SysRole r = sysRoleList.stream()
                                            .filter(sr -> sr.getRoleId().equals(roleId))
                                            .findFirst()
                                            .orElse(null);
                                    return r != null && "0".equals(r.getDelFlag());
                                })
                                .collect(Collectors.toSet());
                    }
                }
                break;

            case "5": // 仅本人数据权限
                allowedRoleIds = sysUserRoleList.stream()
                        .filter(ur -> ur.getUserId().equals(currentUserId))
                        .map(SysUserRole::getRoleId)
                        .filter(roleId -> {
                            SysRole r = sysRoleList.stream()
                                    .filter(sr -> sr.getRoleId().equals(roleId))
                                    .findFirst()
                                    .orElse(null);
                            return r != null && "0".equals(r.getDelFlag());
                        })
                        .collect(Collectors.toSet());
                break;

            default:
                allowedRoleIds.clear();
                break;
        }

        // ✅ 6. 从 params Map 中安全提取 beginTime 和 endTime（关键修复！）
        Date beginTime = null;
        Date endTime = null;

        if (role.getParams() != null) {
            Object beginObj = role.getParams().get("beginTime");
            if (beginObj instanceof Date) {
                beginTime = (Date) beginObj;
            } else if (beginObj instanceof String) {
                // 可选：解析字符串为 Date，这里假设前端传的是 Date 对象
            }

            Object endObj = role.getParams().get("endTime");
            if (endObj instanceof Date) {
                endTime = (Date) endObj;
            }
        }

        // 使用 final 变量供 Lambda 使用（满足“有效 final”要求）
        final Date finalBeginTime = beginTime;
        final Date finalEndTime = endTime;

        // 7. 应用查询条件过滤
        Set<Long> finalAllowedRoleIds = allowedRoleIds;
        List<SysRole> result = sysRoleList.stream()
                .filter(r -> "0".equals(r.getDelFlag())) // 未删除
                .filter(r -> finalAllowedRoleIds.contains(r.getRoleId())) // 数据权限
                .filter(r -> role.getRoleId() == null || r.getRoleId().equals(role.getRoleId())) // roleId
                .filter(r -> role.getRoleName() == null || role.getRoleName().isEmpty() ||
                        r.getRoleName().contains(role.getRoleName())) // roleName 模糊
                .filter(r -> role.getStatus() == null || role.getStatus().isEmpty() ||
                        r.getStatus().equals(role.getStatus())) // status
                .filter(r -> role.getRoleKey() == null || role.getRoleKey().isEmpty() ||
                        r.getRoleKey().contains(role.getRoleKey())) // roleKey 模糊
                .filter(r -> {
                    // 时间范围过滤
                    if (finalBeginTime != null && (r.getCreateTime() == null || r.getCreateTime().before(finalBeginTime))) {
                        return false;
                    }
                    return finalEndTime == null || (r.getCreateTime() != null && !r.getCreateTime().after(finalEndTime));
                })
                .sorted(Comparator.comparing(SysRole::getRoleSort)) // 排序
                .collect(Collectors.toList());


        PageDomain pageDomain = TableSupport.buildPageRequest();
        int pageNum = pageDomain.getPageNum();
        int pageSize = pageDomain.getPageSize();

        int total = result.size();

        // 6. 计算分页边界
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, total);

        List<SysRole> pageList;
        if (start >= total || start < 0) {
            pageList = Collections.emptyList();
        } else {
            pageList = result.subList(start, end);
        }

        // 7. 构造 Page 对象（必须是 com.github.pagehelper.Page）
        Page<SysRole> pageResult = new Page<>();
        pageResult.addAll(pageList);
        pageResult.setTotal(total);
        pageResult.setPageNum(pageNum);
        pageResult.setPageSize(pageSize);

        // 8. 返回（虽然是 List，但实际是 Page 类型，getDataTable 可识别）
        return pageResult;

    }

    /**
     * 递归获取指定部门及其所有子部门的 ID 集合
     *
     * @param dept 当前部门
     * @param deptMap 部门 ID -> 部门对象 映射
     * @param allDepts 所有部门列表
     * @return 包含当前部门和所有子部门的 ID 集合
     */
    private Set<Long> getSubDeptIds(SysDept dept, Map<Long, SysDept> deptMap, List<SysDept> allDepts) {
        Set<Long> result = new HashSet<>();
        result.add(dept.getDeptId());

        List<SysDept> children = allDepts.stream()
                .filter(d -> dept.getDeptId().equals(d.getParentId()))
                .toList();

        for (SysDept child : children) {
            result.addAll(getSubDeptIds(child, deptMap, allDepts));
        }

        return result;
    }

    /**
     * 根据用户ID查询角色
     * 
     * @param userId 用户ID
     * @return 角色列表
     */
    @Override
    public List<SysRole> selectRolesByUserId(Long userId)
    {
        List<SysRole> userRoles = roleMapper.selectRolePermissionByUserId(userId);
        List<SysRole> roles = selectRoleAll();
        for (SysRole role : roles)
        {
            for (SysRole userRole : userRoles)
            {
                if (role.getRoleId().longValue() == userRole.getRoleId().longValue())
                {
                    role.setFlag(true);
                    break;
                }
            }
        }
        return roles;
    }

    /**
     * 根据用户ID查询权限
     * 
     * @param userId 用户ID
     * @return 权限列表
     */
    // @Override
    // public Set<String> selectRolePermissionByUserId(Long userId)
    // {
    //     List<SysRole> perms = roleMapper.selectRolePermissionByUserId(userId);
    //     Set<String> permsSet = new HashSet<>();
    //     for (SysRole perm : perms)
    //     {
    //         if (StringUtils.isNotNull(perm))
    //         {
    //             permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
    //         }
    //     }
    //     return permsSet;
    // }

    /**
     * 改造：数据来源使用基础平台的数据
     * @param userId 用户ID
     * @return
     */
    @Override
    public Set<String> selectRolePermissionByUserId(Long userId)
    {

        // 用于存储最终的权限标识（roleKey），自动去重
        Set<String> permsSet = new HashSet<>();

        // 步骤1：获取系统全局缓存的组织数据
        BaseSystemOrg baseSystemOrg = baseSystemService.getSystemOrg().getData();
        if (baseSystemOrg == null) {
            return permsSet; // 如果没有数据，返回空集合
        }

        // 获取四张表的内存数据
        List<SysRole> sysRoleList = baseSystemOrg.getSysRoleList();        // 所有角色
        List<SysUserRole> sysUserRoleList = baseSystemOrg.getSysUserRoleList(); // 用户-角色关系

        // 步骤2：先找出该用户关联的所有角色 ID（roleIds）
        Set<Long> roleIds = new HashSet<>();
        for (SysUserRole userRole : sysUserRoleList) {
            // 匹配 user_id
            if (userRole.getUserId() != null && userRole.getUserId().equals(userId)) {
                roleIds.add(userRole.getRoleId());
            }
        }

        // 如果该用户没有任何角色，直接返回空集合
        if (roleIds.isEmpty()) {
            return permsSet;
        }

        // 步骤3：遍历所有角色，筛选出：
        //   (1) 角色 ID 在 roleIds 中
        //   (2) delFlag == '0'（未删除）
        for (SysRole role : sysRoleList) {
            // 检查角色是否有效（未删除）
            if (role.getRoleId() == null || !"0".equals(role.getDelFlag())) {
                continue; // 跳过已删除或无效角色
            }

            // 检查该角色是否属于当前用户
            if (roleIds.contains(role.getRoleId())) {
                String roleKey = role.getRoleKey();
                if (StringUtils.isNotBlank(roleKey)) {
                    // 去除前后空格，按逗号分割（兼容多个权限写在一个字段的情况）
                    String[] keys = roleKey.trim().split("\\s*,\\s*");
                    // 添加到结果集合（Set 自动去重）
                    permsSet.addAll(Arrays.asList(keys));
                }
            }
        }

        // 返回用户拥有的所有角色权限标识，如 ["admin", "common", "reviewer"]
        return permsSet;
    }

    /**
     * 查询所有角色
     * 
     * @return 角色列表
     */
    @Override
    public List<SysRole> selectRoleAll()
    {
        return SpringUtils.getAopProxy(this).selectRoleList(new SysRole());
    }

    /**
     * 根据用户ID获取角色选择框列表
     * 
     * @param userId 用户ID
     * @return 选中角色ID列表
     */
    @Override
    public List<Long> selectRoleListByUserId(Long userId)
    {
        return roleMapper.selectRoleListByUserId(userId);
    }

    /**
     * 通过角色ID查询角色
     * 
     * @param roleId 角色ID
     * @return 角色对象信息
     */
    @Override
    public SysRole selectRoleById(Long roleId)
    {
        // 获取外部系统返回的角色列表
        List<SysRole> sysRoleList = baseSystemService.getSystemOrg()
                .getData()
                .getSysRoleList();

        if (sysRoleList == null || sysRoleList.isEmpty()) {
            return null;
        }

        // 查找匹配 roleId 的角色，注意 Long 的 equals 安全比较
        return sysRoleList.stream()
                .filter(role -> roleId != null && roleId.equals(role.getRoleId()))
                .findFirst()
                .orElse(null);  // MyBatis 查询查不到时也返回 null，保持行为一致
    }

    /**
     * 校验角色名称是否唯一
     * 
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public boolean checkRoleNameUnique(SysRole role)
    {
        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
        SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName());
        if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验角色权限是否唯一
     * 
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public boolean checkRoleKeyUnique(SysRole role)
    {
        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
        SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey());
        if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验角色是否允许操作
     * 
     * @param role 角色信息
     */
    @Override
    public void checkRoleAllowed(SysRole role)
    {
        if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin())
        {
            throw new ServiceException("不允许操作超级管理员角色");
        }
    }

    /**
     * 校验角色是否有数据权限
     * 
     * @param roleIds 角色id
     */
    @Override
    public void checkRoleDataScope(Long... roleIds)
    {
        if (!SysUser.isAdmin(SecurityUtils.getUserId()))
        {
            for (Long roleId : roleIds)
            {
                SysRole role = new SysRole();
                role.setRoleId(roleId);
                List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);
                if (StringUtils.isEmpty(roles))
                {
                    throw new ServiceException("没有权限访问角色数据！");
                }
            }
        }
    }

    /**
     * 通过角色ID查询角色使用数量
     * 
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    public int countUserRoleByRoleId(Long roleId)
    {
        return userRoleMapper.countUserRoleByRoleId(roleId);
    }

    /**
     * 新增保存角色信息
     * 
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int insertRole(SysRole role)
    {
        // 新增角色信息
        roleMapper.insertRole(role);
        return insertRoleMenu(role);
    }

    /**
     * 修改保存角色信息
     * 
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateRole(SysRole role)
    {
        // 修改角色信息
        roleMapper.updateRole(role);
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId());
        return insertRoleMenu(role);
    }

    /**
     * 修改角色状态
     * 
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public int updateRoleStatus(SysRole role)
    {
        return roleMapper.updateRole(role);
    }

    /**
     * 修改数据权限信息
     * 
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int authDataScope(SysRole role)
    {
        // 修改角色信息
        roleMapper.updateRole(role);
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId());
        // 新增角色和部门信息（数据权限）
        return insertRoleDept(role);
    }

    /**
     * 新增角色菜单信息
     * 
     * @param role 角色对象
     */
    public int insertRoleMenu(SysRole role)
    {
        int rows = 1;
        // 新增用户与角色管理
        List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
        for (Long menuId : role.getMenuIds())
        {
            SysRoleMenu rm = new SysRoleMenu();
            rm.setRoleId(role.getRoleId());
            rm.setMenuId(menuId);
            list.add(rm);
        }
        if (list.size() > 0)
        {
            rows = roleMenuMapper.batchRoleMenu(list);
        }
        return rows;
    }

    /**
     * 新增角色部门信息(数据权限)
     *
     * @param role 角色对象
     */
    public int insertRoleDept(SysRole role)
    {
        int rows = 1;
        // 新增角色与部门（数据权限）管理
        List<SysRoleDept> list = new ArrayList<SysRoleDept>();
        for (Long deptId : role.getDeptIds())
        {
            SysRoleDept rd = new SysRoleDept();
            rd.setRoleId(role.getRoleId());
            rd.setDeptId(deptId);
            list.add(rd);
        }
        if (list.size() > 0)
        {
            rows = roleDeptMapper.batchRoleDept(list);
        }
        return rows;
    }

    /**
     * 通过角色ID删除角色
     * 
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRoleById(Long roleId)
    {
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDeptByRoleId(roleId);
        return roleMapper.deleteRoleById(roleId);
    }

    /**
     * 批量删除角色信息
     * 
     * @param roleIds 需要删除的角色ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRoleByIds(Long[] roleIds)
    {
        for (Long roleId : roleIds)
        {
            checkRoleAllowed(new SysRole(roleId));
            checkRoleDataScope(roleId);
            SysRole role = selectRoleById(roleId);
            if (countUserRoleByRoleId(roleId) > 0)
            {
                throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
            }
        }
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenu(roleIds);
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDept(roleIds);
        return roleMapper.deleteRoleByIds(roleIds);
    }

    /**
     * 取消授权用户角色
     * 
     * @param userRole 用户和角色关联信息
     * @return 结果
     */
    @Override
    public int deleteAuthUser(SysUserRole userRole)
    {
        return userRoleMapper.deleteUserRoleInfo(userRole);
    }

    /**
     * 批量取消授权用户角色
     * 
     * @param roleId 角色ID
     * @param userIds 需要取消授权的用户数据ID
     * @return 结果
     */
    @Override
    public int deleteAuthUsers(Long roleId, Long[] userIds)
    {
        return userRoleMapper.deleteUserRoleInfos(roleId, userIds);
    }

    /**
     * 批量选择授权用户角色
     * 
     * @param roleId 角色ID
     * @param userIds 需要授权的用户数据ID
     * @return 结果
     */
    @Override
    public int insertAuthUsers(Long roleId, Long[] userIds)
    {
        // 新增用户与角色管理
        List<SysUserRole> list = new ArrayList<SysUserRole>();
        for (Long userId : userIds)
        {
            SysUserRole ur = new SysUserRole();
            ur.setUserId(userId);
            ur.setRoleId(roleId);
            list.add(ur);
        }
        return userRoleMapper.batchUserRole(list);
    }
}
